<template>
  <div class="hauner gas-table__box">
    <el-table
      ref="haTable"
      class="mt20"
      :size="size"
      :border="border"
      :data="tableData"
      :stripe="stripe"
      :header-cell-style="headerCellStyle"
      :header-cell-class-name="headerCellClassName"
      :highlight-current-row="highlightCurrentRow"
      :height="height"
      :span-method="spanMethod"
      :current-row-key="currentRowKey"
      :row-key="rowKey"
      :empty-text="emptyText"
      @select="select"
      @select-all="selectAllEvent"
      @selection-change="selectionChange"
      @cell-mouse-enter='cellMouseEnter'
      @cell-click="onCellClick"
      @row-click="onRowClick"
      @sort-change="e => $emit('sort-change', e)"
    > 
      <template #empty>
        <slot name="empty">{{ emptyText }}</slot>
      </template>
      <template v-for="(col, index) in tableHead">
        <el-table-column
          v-if="col.type == 'radio'"
          :key="index + (col.label ? col.label : col.type)"
          label="选择"
          width="55"
          :selectable="col.selectable"
        >
          <template #default="{ row, $index }">
            <el-radio
              v-model="radioSelect"
              :disabled="!col.selectable(row)"
              style="text-algin:'center'"
              :index="$index"
              :label="row"
              >&nbsp;</el-radio
            >
          </template>
        </el-table-column>
        <el-table-column  v-else        
          :key="col[headOption.prop]"
          :type="col[headOption.type]"
          :prop="col[headOption.prop]"
          :label="col[headOption.label]"
          :align="col[headOption.align]"
          :width="col[headOption.width]"
          :sortable="col[headOption.sortable]"
          :min-width="`${col[headOption.label]?.length * 14 + 24}px`"
          :fixed="col[headOption.fixed]"
          :selectable="col[headOption.selectable]"
          :show-overflow-tooltip="!col[headOption.slot]"
          :formatter="r => (col.filter ? col.filter(r) : r[col[headOption.prop]] ?? defaultValue)"
        >
          <template v-if="col[headOption.slot]" #default="{row, $index}">
            <slot :name="col[headOption.slot]" :row="row" :col="col" :ind="$index"></slot>
          </template>
          <template v-else-if="!col[headOption.type]" #default="{row}">
            <span :class="col.classFn ? col.classFn(row) : ''">{{ col.filter ? col.filter(row) : row[col[headOption.prop]] ?? defaultValue}}</span>
          </template>
          <template #header>
            <slot v-if="col[headOption.headSlot]"  :name="col[headOption.headSlot]" :col="col"></slot>
            <ha-table-handle v-else-if="col[headOption.slot]=='handle' && hasHeadHandle" v-model="tableHead" :head="head" :col="col" @close="doLayout"></ha-table-handle>
            <span v-else>{{ col[headOption.label] }}</span>
          </template>
          <el-table-column
            v-for="chi in col[headOption.children]"
            :key="chi[headOption.prop]"
            :prop="chi[headOption.prop]"
            :label="chi[headOption.label]"
            :align="chi[headOption.align]"
            :width="chi[headOption.width]"
            :sortable="chi[headOption.sortable]"
            :min-width="`${chi[headOption.label]?.length * 14 + 24}px`"
            :fixed="col[headOption.fixed]"
            :selectable="chi[headOption.selectable]"
            :show-overflow-tooltip="!chi[headOption.slot]"
            :formatter="r => r[chi[headOption.prop]] ?? defaultValue"
          >
            <template v-if="chi[headOption.slot]" #default="obj">
              <slot :name="chi[headOption.slot]" :obj="obj"></slot>
            </template>
            <template v-if="chi[headOption.headSlot]" #header>
              <slot :name="chi[headOption.headSlot]" :col="chi" ></slot>
            </template>
            <template v-else-if="chi[headOption.slot]=='handle' && hasHeadHandle" #header>
              <ha-table-handle v-model="tableHead" :head.sync="head" :col="chi" @close="doLayout"></ha-table-handle>
            </template>
          </el-table-column>
        </el-table-column>
      </template>
    </el-table>
    <el-pagination
      v-if="hasPagination"
      class="mt20"
      :current-page="pageOption.current"
      background
      :page-sizes="[2, 5, 10, 15, 20, 30, 50, 100]"
      :page-size="pageOption.size"
      :layout="pageLayout"
      :total="total"
      @size-change="onSizeChange"
      @current-change="onPageChange"
    >
    </el-pagination>
  </div>
</template>
<script>
import { deepClone, isEmpty, sleep } from '../../utils'
import tableHandle from './tableHandle.vue';
export default {
  components: { tableHandle },
  name: 'HaTable',
  props: {
    emptyText: { type: String, default: '暂无数据' },
    currentRowKey: { type: String, default: '7' },
    rowKey: { type: String, default: 'id' },
    highlightCurrentRow: { type: Boolean, default: true },
    clickTriggerSelection: { type: Boolean, default: true },
    hasPagination: { type: Boolean, default: true },
    pageOption: { type: Object, default: () => ({}) },
    total: { type: Number, default: 0 },
    head: { type: Array, default: () => [] },
    height: { type: [String, Number], default: `calc(100% - 1px)` },
    tableData: { type: Array, default: () => [] },
    headProp: { type: Object, default: () => ({}) },
    stripe: { type: Boolean, default: false },
    border: { type: Boolean, default: false },
    headerCellStyle: { type: [Function, Object], default: () => ({}) },
    spanMethod: { type: Function, default: () => {} },
    headerCellClassName: { type: String, default: 'gary-header__table' },
    defaultValue: { type: [String, Number], default: ' ' },
    pageStyle: { type: String, default: '' },
    radio: { type: Boolean, default: false },
    radioModel: {type: Object, default: null},
    size: { type: String, default: 'medium' },
    hasHeadHandle: { type: Boolean, default: false },
  },
  data: () => ({
    radioSelect: null,
    tableHead: [],
    headOption: {
      prop: 'prop',
      label: 'label',
      children: 'child',
      align: 'a',
      width: 'w',
      slot: 'slot',
      type: 'type',
      headerSlot: 'headerSlot',
      selectable: 'selectable',
      fixed: 'fixed',
      headSlot: 'headSlot',
      sortable: 'sortable',
    }
  }),
  computed: {},
  watch: {
    radioSelect(v) {
      this.select([v], v)
    },

    radioModel(v){
      if(!isEmpty(v)){
        this.radioSelect = v
        this.$forceUpdate()
      }
    },

    tableData(v) {
      this.doLayout()
    },

    head() {
      if(!this.hasHeadHandle) return
      this.doLayout()
      this.refreshHead()
    }
  },
  created() {
    this.init()
  },
  mounted() {},
  methods: {
    refreshTable() {
      this.$nextTick( () => {
        this.refreshHead()
        this.$nextTick( () => this.doLayout())
      })
    },
    init() {
      this.pageLayout = this.pageStyle || 'total, sizes, prev, pager, next, jumper'
      this.headOption = { ...this.headOption, ...this.headProp } 
      this.head.forEach(el => {
        el.checked = el.checked === undefined ? true : el.checked
        if(this.hasHeadHandle)el.w = el.w || el.label?.length * 14 + 24
        if(el.solt == 'handle') el.fixed = 'right'
      })
      this.refreshHead()
    },
    
    refreshHead() {
      this.tableHead = []
      if(!this.hasHeadHandle) {
        this.tableHead = deepClone(this.head)
      }else{
        let list = this.head.filter(el => el.checked)
        this.tableHead = deepClone(list)
      }
    },
    selectable(row) {
      return true
    },

    onSizeChange(size) {
      this.pageOption.size = size
      this.pageOption.current = 1
      this.$emit('pagination', this.pageOption)
    },

    selectAll() {
      this.$nextTick( () => {        
        this.$refs.haTable.clearSelection()
        this.$nextTick( () => {
          this.$refs.haTable.toggleAllSelection()
          this.doLayout()
          this.$forceUpdate()
        })
      })
      
    },

    onPageChange(page) {
      this.pageOption.current = page
      this.$emit('pagination', this.pageOption)
    },

    onCellClick(row, column, cell, event) {
      this.$emit('cell-click', row, column, cell, event )
    },

    onRowClick(row, column, event) {
      if(this.clickTriggerSelection){
        this.radioSelect = row
      }
      this.$emit('row-click',  row, column, event )
    },

    selectionChange(selection) {
      this.$emit('selection-change', selection)
    },

    select(selection, row) {
      this.$emit('select', selection, row )
    },

    selectAllEvent(e) {
      this.$emit('select-all', e)
    },

    cellMouseEnter(	row, column, cell, event) {
      this.$emit('cell-mouse-enter', 	row, column, cell, event)
    },

    async doLayout(){
      while(true) {
        if(this.$refs?.haTable){
          this.$nextTick( () => this.$refs?.haTable?.doLayout() )          
          return
        }
        await sleep(100)
      }
    },

    
  }
}
</script>
<style lang="scss" scoped>
.hauner.gas-table__box{
  height: 100%;
}
</style>
